package com.softhinker.ke24.unit2.solution;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Timer;
import java.util.TimerTask;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;

import ke24.ga.extension.PackageGenerator;
import ke24.ga.extension.VariousSizeLoadDistribution;

import com.softhinker.ke24.unit2.MainFace.DataPanelCreator;
import com.softhinker.ke24.unit2.MainFace.SolutionPanelCreator;
import com.softhinker.ke24.unit2.data.DataPanel;
import com.softhinker.ke24.unit2.data.DataRetriever;
import com.softhinker.ke24.unit2.settings.Settings;

public class SolutionPanel implements SolutionPanelCreator, ActionListener 
{
	private JButton startButton;
	private JButton stopButton;
	private JButton resetButton;
	private Settings settings;
	private Evolver evolver;
	
	private final DataPanel dataPanelCreator = new DataPanel();
	private final DataRetriever dataRetriever = new PackageGenerator();
	
	public SolutionPanel(Settings settings)
	{
		this.settings = settings;
		
	}
	

	public JComponent createSolutionPanel() {
	    
		JPanel solutionPanel = new JPanel();
		solutionPanel.setLayout(new BorderLayout());
		solutionPanel.add(initializeDataPanel(), BorderLayout.CENTER);
		solutionPanel.add(initializeControlPanel(), BorderLayout.SOUTH);
		return solutionPanel;
	}

	private JComponent initializeDataPanel()
	{
		return dataPanelCreator.createDataPanel(this.dataRetriever);
	}
	
	private JComponent initializeControlPanel()
	{
		JPanel controlPanel = new JPanel();
		
		startButton = new JButton("Start");
		startButton.setActionCommand("Start");
		startButton.addActionListener(this);
		startButton.setEnabled(true);
		
		stopButton = new JButton("Stop");
		stopButton.setActionCommand("Stop");
		stopButton.addActionListener(this);
		stopButton.setEnabled(false);
		
		resetButton = new JButton("Reset");
		resetButton.setActionCommand("Reset");
		resetButton.addActionListener(this);
		resetButton.setEnabled(false);
		
		controlPanel.add(startButton);
		controlPanel.add(stopButton);
		controlPanel.add(resetButton);
		
		return controlPanel;
	}


	public void actionPerformed(ActionEvent event)
	{
		if(event.getActionCommand().equals("Start"))
		{
			startEvolving();
		}
		else if(event.getActionCommand().equals("Stop"))
		{
			stopEvolving();
		}else if (event.getActionCommand().equals("Reset")) {
		    reset();
		}
	}
	
	private Thread evolverThread;
	private TimerTask timerTask;
	private boolean stopNow = false;
	private void startEvolving() 
	{
		startButton.setEnabled(false);
		stopButton.setEnabled(true);
			
		
		this.evolver = new VariousSizeLoadDistribution(dataPanelCreator,
                this.settings.getPopulationSize(),
                this.settings.getMutationRate(), 
                this.settings.getMutationRateStrategy(),
                this.settings.getIterationCount(),
                this.dataRetriever.getPackages());
		
		System.out.println("Mutation rate: " + settings.getMutationRate() + " population size: " + settings.getPopulationSize() + " mutation rate strategy: " + settings.getMutationRateStrategy());
		if(this.settings.getIterationDuration() > 0)
		{//Stopping condition is by time
			System.out.println("Stopping condition : " + this.settings.getIterationDuration() + " minutes");
			Timer timer = new Timer();
			timerTask = new TimerTask(){

				@Override
				public void run() {
					stopNow = true;
					stopEvolving();
				}
				
			};
			
			timer.schedule(timerTask, 
					this.settings.getIterationDuration() * 60 * 1000);
			
			evolverThread = new Thread(new Runnable(){

				public void run() {
					while(!stopNow)
					{
						evolver.evolve();
					}
				}
				
			});
			
			evolverThread.start();
		}
		else
		{//Stopping condition is by count
			System.out.println("Stopping condition : " + this.settings.getIterationCount() + " iterations");
			final int count = this.settings.getIterationCount();
			evolverThread = new Thread(new Runnable(){

				public void run() {
					for(int i=0; i< count; i++)
					{
						if(stopNow) return;
						
						evolver.evolve();
					}
					stopEvolving();
				}
				
			});
			
			this.evolverThread.start();
		}
	}
	
	private void stopEvolving()
	{
		if(this.timerTask != null)
		{
			this.timerTask.cancel();
			this.timerTask = null;
		}
		this.stopNow = true;
		this.evolverThread = null;
		startButton.setEnabled(false);
		stopButton.setEnabled(false);
		resetButton.setEnabled(true);
	}
	
	private void reset() {
	    this.dataPanelCreator.reset();
	    startButton.setEnabled(true);
	    resetButton.setEnabled(false);
	    evolver.reset(this.settings);
	    this.stopNow = false;
	}
}
